import axios from 'axios';
import router from '@/router';

const baseURL = '';

// 创建axios实例
const service = axios.create({
    // 请求头配置 token
    headers: { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' },
    // 基础路径
    baseURL,
    // 请求连接超时设置
    timeout: 2 * 60 * 1000,
    // 表示跨域请求时是否需要使用凭证，开启后，后端服务器要设置允许开启
    withCredentials: true,
});

// request 请求拦截器
service.interceptors.request.use(
    (config: any) => {
        // 发起请求时，重新获取最新的token，这一步有时很重要，因为创建 axios 实例的时候，
        // 获取到的 token 未必是有效的，或说未必能获取到
        const token: string | null = localStorage.getItem('access_token');

        config.headers['Authorization'] = `Bearer ${token}`;

        // 特殊配置：设置下载获取 excel 接口的返回值为 blob。这在异步下载文件时有时会显得很有用。
        if (config.url === '/api/excel/download') {
            config.responseType = 'blob';
        }

        return config;
    },
    (error: any) => {
        // console.warn(error);
        return Promise.reject(error);
    },
);

// response 响应拦截器
service.interceptors.response.use(
    (response: any) => {
        // console.log(response, 'response');

        const { data: res, status } = response;
        if (status === 201) {
            // 成功了
            console.log('创建成功');
        }
        if (status === 200) {
            // 成功了
            console.log(res.message);
        }
        if (res instanceof Blob) {
            return res;
        }

        // code === -12345，token失效，跳转到登录页重新登陆
        if (res.code === -12345) {
            /* // 一个特殊功能：访问一个地址没权限，记录下该地址，登录获取后可以重定向到该地址
            let currentUrl = window.location.href
            const index = currentUrl.indexOf('#')
            const str = currentUrl.substr(index + 1, 6)
            // 如当前页不是登录页则跳转到登录页并缓存当前页地址
            if (str !== '/Login') {
              localStorage.setItem('currentUrl', window.location.href)
              navigate({ name: 'Login' }).then()
            } */

            // navigate('login')
            return res;
        }

        // 特殊配置：异步下载文件中有用，一般用不上，导出 word、excel 文件接口
        // 注意此时返回的是完整的 response，开放更多信息便于处理下载过程
        const url = response?.config?.url;
        if (url === '/api/word/download' || url === '/api/excel/download') {
            response.headers.responseType = 'blob';
            return response;
        }

        // 前后端约定 code 为100表示接口正常响应，取相反值则表示此时接口非正常响应，
        // 此时，统一开启接口返回的业务类型的错误提示，这样就不用在每个接口都处理，
        // 例如账号密错误时，自动捕获接口返回的业务类型的“错误”提示。注意这是业务类型的“错误”，不是bug。
        if (res.code !== 0) {
            console.log(res.message || '服务器开小差啦，请稍后重试');

            // 直接reject有时非常有用，统一拦截，这时，调用接口的回调.then()不会在执行，
            // 而是改为执行.catch()，这样做的好处是我们无需考虑在具体的每一个接口中
            // 的.then()是否是正常响应，只接受正常响应的 code 为 100 的。非100不进入.then()
            // 当然这对后端按约定编写接口有较高的要求，也有弊端，就是非100无法在.then()中接收到。
            // return Promise.reject(res.message)

            return res;
        } else {
            return res;
        }
    },
    (error: any) => {
        const messageText = error?.response?.data?.message || error?.message || '接口错误';
        console.log(messageText);

        if (error.response.status === 401) {
            if (messageText === '登录过期') {
                // 登录过期，重新登录
                localStorage.clear();
                // window.location.reload();
                router.navigate('/login', {
                    replace: true,
                    state: {
                        from: window.location.pathname,
                    },
                });
            } else {
                // 登录密码错误
            }
        }
        return Promise.reject(error);
    },
);

const request = {
    get(url: string, params?: any) {
        return new Promise((resolve, reject) => {
            service({
                method: 'get',
                url,
                params,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json;charset=UTF-8',
                },
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    post(url: string, params?: any) {
        return new Promise((resolve, reject) => {
            service({
                method: 'post',
                url,
                data: params,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json;charset=UTF-8',
                },
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    patch(url: string, params?: any) {
        return new Promise((resolve, reject) => {
            service({
                method: 'patch',
                url,
                data: params,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json;charset=UTF-8',
                },
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    delete(url: string, params?: any) {
        return new Promise((resolve, reject) => {
            service({
                method: 'delete',
                url,
                data: params,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json;charset=UTF-8',
                },
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    postMultipart(url: string, params?: any) {
        return new Promise((resolve, reject) => {
            service({
                method: 'post',
                url,
                data: params,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'multipart/form-data;boundary=' + new Date().getTime(),
                },
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    put(url: string, params?: any) {
        return new Promise((resolve, reject) => {
            service({
                method: 'put',
                url,
                data: params,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json;charset=UTF-8',
                },
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    getBlob(url: string, { params, headers }: any) {
        return new Promise((resolve, reject) => {
            service({
                url,
                method: 'get',
                responseType: 'blob',
                params,
                headers,
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
    getBuffer(url: string, { params, headers }: any) {
        return new Promise((resolve, reject) => {
            service({
                url,
                method: 'get',
                responseType: 'arraybuffer',
                params,
                headers,
            })
                .then((res: any) => {
                    resolve(res);
                })
                .catch((error: any) => {
                    reject(error);
                });
        });
    },
};

export { service, request, baseURL };
